//
// Created by Administrator on 2020/10/14.
//

#include <poll.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include "../include/amfApi.h"
#include "../../../ccore/sctp/include/sctpApi.h"

S_AmfContext *gpAmfContext = NULL;

int32_t AMF_Init(void)
{
    int32_t rc;

    gpAmfContext = OS_MemCalloc(1, sizeof(S_AmfContext));
    IF_RETURN(==, NULL, gpCnContext, O5G_RC_ER, "AMF_Init() OS_MemCalloc() error!\n");

    rc = SCTPS_Init(&gpAmfContext->sctpFd);
    IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "AMF_Init() SCTPS_Init() error!\n");
    rc = SCTPS_Bind(gpAmfContext->sctpFd, "127.0.0.1", NGAP_SCTP_PORT);
    IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "AMF_Init() SCTPS_Bind() error!\n");
    rc = SCTPS_Listen(gpAmfContext->sctpFd);
    IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "AMF_Init() SCTPS_Listen() error!\n");

    return O5G_RC_OK;
}

int32_t AMF_Final(void)
{
    int32_t rc;

    rc = SCTPS_Final(gpAmfContext->sctpFd);
    IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "AMF_Final() SCTPS_Final() error!\n");

    OS_MemFree(gpAmfContext);

    return O5G_RC_OK;
}

void AMF_Process(int sctpFd)
{
    int32_t rc;
    int msgFlags;
    struct sctp_sndrcvinfo sri;
    socklen_t fromLen;
    struct sockaddr_in nb_addr;

    msgFlags = 0;
    fromLen = sizeof(nb_addr);
    rc = sctp_recvmsg(sctpFd, gpAmfContext->sockBuffer, SOCK_BUFFER_SIZE, (struct sockaddr*)&nb_addr, &fromLen, &sri, &msgFlags);
    if (rc > 0)
    {
        if (msgFlags & MSG_NOTIFICATION)
        {
        }
        else
        {
        }
    }
}

void *AMF_Task(void* arg)
{
    int32_t rc;
    struct pollfd pfd;
    uint64_t lastTimeStamp;

    while (1)
    {
        pfd.fd = gpAmfContext->sctpFd;
        pfd.events = POLLIN | POLLNVAL | POLLERR | POLLHUP;
        pfd.revents = 0;

        rc = poll(&pfd, 1, 5);
        if (rc > 0)
        {
            if (pfd.revents & POLLIN)
            {
                AMF_Process(pfd.fd);
            }
            if (pfd.revents & (POLLNVAL | POLLERR | POLLHUP))
            {
                CSP_LOG_ERR(CN_MD_AMF, "sock[%d] receive unexpected events[%d].\n", pfd.fd, pfd.revents);
                return NULL;
            }
        }
        pthread_testcancel();
    }
    return NULL;
}

int32_t AMF_Start(void)
{
    int32_t rc;

    rc = OS_ThreadCreate(&gpAmfContext->tid, AMF_Task, NULL);
    IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "AMF_Start() OS_ThreadCreate() error!\n");

    return O5G_RC_OK;
}

int32_t AMF_Stop(void)
{
    int32_t rc;

    rc = OS_ThreadCancel(gpAmfContext->tid);
    IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "AMF_Stop() OS_ThreadCancel() error!\n");

    return O5G_RC_OK;
}
